using System;
using System.Collections.Generic;
using Microsoft.Pex.Framework;

namespace Benchmarks
{
    public class EnclosingCommand2
    {
        private EnclosingCommand command;

        public EnclosingCommand2(EnclosingCommand command)
        {
            this.command = command;
        }

        public void Execute(object[] parameters)
        {
            command.Execute(parameters);
        }
    }


    public class EnclosingCommand
    {
        private Command command;

        public EnclosingCommand(Command command)
        {
            this.command = command;
        }

        public void Execute(object[] parameters)
        {
            command.Execute(parameters);
        }
    }

    public class Command
    {
        private IMethodInfo info;
        private string name;

        public string Name
        {
            get { return name; }
        }

        public Command()
        {
        }

        public Command(IMethodInfo _methodInfo, string name)
        {
            this.info = _methodInfo;
            this.name = name;
        }

        public void Execute(object[] parameters)
        {
            if (parameters.Length != info.ParameterInfos.Count)
            {
                throw new Exception("not match");
            }
            info.Execute(parameters);
        }

        public void ExecuteCount(object[] parameters)
        {
            if (parameters.Length != info.ParaCount())
            {
                throw new Exception("not match");
            }
            info.Execute(parameters);
        }

        public void ExecuteMultiple(object[] parameters)
        {
            if (parameters.Length != info.ParameterInfos.Count)
            {
                throw new Exception("not match");
            }
            info.Execute(parameters);
        }
    }

    public interface IMethodInfo
    {
        List<object> ParameterInfos { get; }
        void Execute(object[] parameters);
        int ParaCount();
    }

    public class MethodInfo:IMethodInfo
    {
        private List<object> infos;
        private int count;

        public MethodInfo()
        {
            this.infos = new List<object>();
        }

        public List<object> ParameterInfos
        {
            get { return infos; }
        }

        public void AddParameter(object parameter)
        {
            infos.Add(parameter);
        }

        public void AddCount()
        {
            count++;
        }

        public int ParaCount()
        {
            return count;
        }

        public void Execute(object[] parameters)
        {
            foreach (object o in parameters)
            {
                Console.WriteLine("object is: " + o);
            }
        }
    }

    [PexClass(typeof (Command))]
    public partial class CommandTest
    {
        [PexMethod]
        public void TestEnclosingClass2(EnclosingCommand2 enclosing, object[] parameters)
        {
            PexAssume.IsTrue(parameters.Length == 3);
            enclosing.Execute(parameters);
        }


        [PexMethod]
        public void TestEnclosingClass(EnclosingCommand enclosing, object[] parameters )
        {
            enclosing.Execute(parameters);
        }

        [PexMethod]
        public void TestExecute(Command command, object[] parameters)
        {
            command.Execute(parameters);
        }

        [PexMethod]
        public void TestExecuteCount(Command command, object[] parameters)
        {
            PexAssume.IsTrue(parameters.Length == 3);
            command.ExecuteCount(parameters);
        }

        [PexMethod]
        public void TestExecuteMultiple(Command command, object[] parameters)
        {
            command.ExecuteMultiple(parameters);
        }
    }
}